package com.llu.serial.fastjson.serializer;

import com.llu.serial.fastjson.FieldInfo;
import com.llu.serial.fastjson.JsonConfig;
import com.llu.serial.fastjson.Utils;

/**
 * 字段序列化器
 * 用于将对象的特定字段序列化为JSON格式的字符串
 */
public class FieldSerializer {

    // 存储字段信息
    private final FieldInfo fieldInfo;
    // 存储字段名对应的键，用于JSON序列化时使用
    private final String key;
    // 标识字段类型是否为基本类型或其包装类
    private final boolean isPrimitive;

    /**
     * 构造函数，初始化字段信息、键和字段是否为基本类型
     *
     * @param fieldInfo 字段信息，包含字段名、类型等
     */
    public FieldSerializer(FieldInfo fieldInfo) {
        this.fieldInfo = fieldInfo;
        // 为字段名添加JSON格式所需的双引号
        this.key = '"' + fieldInfo.name + "\":";
        // 判断字段类型是否为基本类型或其包装类
        Class type = fieldInfo.type;
        this.isPrimitive = Utils.isBox(type) || type.isPrimitive();
    }

    /**
     * 将对象的指定字段序列化为JSON格式的字符串
     *
     * @param serializerContext 序列化上下文，包含序列化过程中所需的信息
     * @param config            JSON配置，包含自定义序列化器等信息
     * @param object            需要序列化的对象
     * @return 序列化后的JSON格式字符串
     */
    public String serializer(SerializerContext serializerContext, JsonConfig config, Object object) {
        // 获取对象中当前字段的值
        Object o = fieldInfo.get(object);
        // 如果字段值为空，直接返回空字符串
        if (null == o) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        // 如果字段类型为基本类型或其包装类
        if (isPrimitive) {
            sb.append(key);
            sb.append(o);
        } else if (Utils.isString(fieldInfo.type)) {
            // 如果字段类型为字符串
            sb.append(key);
            sb.append("\"");
            sb.append(o);
            sb.append("\"");
        } else {
            // 如果字段类型为JavaBean或List等复杂类型
            String cacheKey = String.valueOf(serializerContext.refrence.get(key));
            if (cacheKey != null && cacheKey.equals(object)) {
                // 检查是否有循环引用，如果有则直接返回当前已构建的字符串
                return sb.toString();
            }
            serializerContext.refrence.put(key, object);
            // 获取对应类型的自定义序列化器
            ObjectSerializer serializer = config.getSerializer(fieldInfo.type);
            sb.append(key);
            // 使用自定义序列化器进行序列化
            serializer.serializer(serializerContext, config, sb, o);
        }
        return sb.toString();
    }
}

